﻿
Imports System.Threading

Public Module threads

    Private Class backendThread(Of _intervalMs As _int64)
        Private Shared ReadOnly t As Thread = Nothing
        Private Shared ReadOnly intervalMs As Int64 = 0
        Private Shared vs As memblock(Of void) = Nothing

        Shared Sub New()
            intervalMs = +(alloc(Of _intervalMs)())
            vs = New memblock(Of void)()
            t = startThread(AddressOf backendThreadCall)
            t.Name = "SHARED_BACKEND_" + Convert.ToString(intervalMs) + "MS_THREAD"
            t.IsBackground = True
            t.Priority = ThreadPriority.BelowNormal
        End Sub

        Private Shared Sub backendThreadCall()
            While True
                Dim i As Int64 = 0
                While i < vs.size()
                    Dim v As void = Nothing
                    v = atomic.read(vs(i))
                    If Not v Is Nothing Then
                        timelimitOperation.start()
                        void_(v)
                        timelimitOperation.finish(New lazier(Of String)(Function() As String
                                                                            Return invokeMethodIdentity(v)
                                                                        End Function))
                        sleep(intervalMs \ vs.size())
                    End If
                    i += 1
                End While
            End While
        End Sub

        Friend Shared Function queueInBackendThread(ByVal v As void) As Int64
            assert(Not v Is Nothing)
            Dim rtn As Int64 = 0
            SyncLock vs
                rtn = vs.size()
                vs.append(v)
            End SyncLock

            Return rtn
        End Function

        Friend Shared Function removeFromBackendThread(ByVal id As Int64) As Boolean
            Dim rtn As Boolean = False
            If vs.availableIndex(id) Then
                atomic.eva(vs(id), Nothing)
                rtn = True
            End If

            Return rtn

        End Function
    End Class

    Public Function queueInBackendThread(Of intervalMs As _int64)(ByVal v As void) As Int64
        If Not v Is Nothing Then
            Return backendThread(Of intervalMs).queueInBackendThread(v)
        Else
            Return npos
        End If
    End Function

    Public Function queueInBackendThread(ByVal v As void) As Int64
        Return queueInBackendThread(Of _500)(v)
    End Function

    Public Function removeFromBackendThread(Of intervalMs As _int64)(ByVal id As Int64) As Boolean
        Return backendThread(Of intervalMs).removeFromBackendThread(id)
    End Function

    Public Function removeFromBackendThread(ByVal id As Int64) As Boolean
        Return removeFromBackendThread(Of _500)(id)
    End Function

#If PocketPC OrElse Smartphone Then
    Private finishInitial As Boolean
    Private threadPara As threadStart2
    Private mutex As Mutex = Nothing
    Public Delegate Sub ParameterizedThreadStart(ByVal obj As Object)

    Public Class threadStart2
        Public start As ParameterizedThreadStart
        Public para As Object
    End Class
#End If

    Public Function startThread(ByVal invoke As ThreadStart) As Thread
        Dim thread As Thread = Nothing
        thread = New Thread(invoke)
        thread.Start()
        Return thread
    End Function

#If PocketPC OrElse Smartphone Then
    Private Sub threadsub()
        assert(not finishInitial, "should not finishInitial before thread really caught the parameter.")
        Dim para As threadstart2 = Nothing 
        para = threadPara
        finishInitial = true
        assert(Not para Is Nothing, "cannot get valid parameter.")
        para.start(para.para)
    End Sub
#Else
#If RETIRED Then
    Private Sub threadsub(ByVal obj As Object)
        Dim para As threadStart2 = Nothing
        para = convertor.cast(Of threadStart2)(obj)
        assert(Not para Is Nothing, "cannot get valid parameter.")
        para.start(para.para)
    End Sub
#End If
#End If

    Public Function startThread(ByVal invoke As ParameterizedThreadStart, ByVal parameter As Object) As Thread
        Dim thread As Thread = Nothing
#If PocketPC OrElse Smartphone Then
        thread = New Thread(AddressOf threadsub)
        Dim para As threadStart2 = Nothing
        para = New threadStart2()
        para.start = invoke
        para.para = parameter
        assert(Mutex.WaitOne(), "cannot lock mutex when startThread.")
        threadPara = para
        thread.Start()
        While Not finishInitial
            sleep(64)
        End While
        Mutex.ReleaseMutex()
        'max qps on WindowsCE is 1000/defaultWaitTime, accroding to current setting, is about 64
#Else
        thread = New Thread(invoke)
        thread.Start(parameter)
        'seems no max qps limit on other platform
#End If

        Return thread
    End Function

#If PocketPC OrElse Smartphone Then
    Sub New()
        mutex = New Mutex()
    End Sub
#End If

    Public Const INVALID_THREAD_ID As Int32 = 0

    Private Class _threadID
        <ThreadStatic()> Private Shared _currentThreadID As Int32

        Shared Sub New()
            assert(INVALID_THREAD_ID = [default](Of Int32)())
        End Sub

        Public Shared Function currentThreadID() As Int32
            Dim rtn As Int32 = 0
            rtn = _currentThreadID
            If rtn = INVALID_THREAD_ID Then
                rtn = Thread.CurrentThread().ManagedThreadId()
                _currentThreadID = rtn
            End If

            Return rtn
        End Function
    End Class

    Public Function currentThreadID() As Int32
        Return _threadID.currentThreadID()
    End Function
End Module
